# 导入模块
import pygame
import random
import sys
import time
import tkinter as tk
import _thread
from pygame.locals import *
from datetime import datetime

# TkInter界面
root = tk.Tk()
root.title("矿工小游戏：设置")
root.iconphoto(False, tk.PhotoImage(file="man.png"))
w_seed = tk.Label(root, text="地图种子（同一个种子会生成相同的地图，空着表示随机种子）: ")
seed = tk.Entry(root)
do_ai = tk.IntVar()
ai_cb = tk.Checkbutton(root, text="由人机操作", variable=do_ai)
copyr = tk.Label(root, text="矿工小游戏 Copyright © 2021 王翊临 All Right Reserved")
# 确定
def cmd_confirm():
    global gameseed
    gameseed = seed.get()
    if gameseed == '':
        gameseed = random.randint(0, 1e10)
    else:
        gameseed = int(gameseed)
    root.destroy()
# 取消
def cmd_cancel():
    root.destroy()
    sys.exit()
confirm = tk.Button(root, text="确定", command=cmd_confirm)
cancel = tk.Button(root, text="取消", command=cmd_cancel)
w_seed.grid(row=0, column=0, columnspan=2)
seed.grid(row=0, column=2)
ai_cb.grid(row=1, column=0)
confirm.grid(row=2, column=0)
cancel.grid(row=2, column=1)
root.protocol("WM_DELETE_WINDOW", cmd_cancel)
root.mainloop()

# 地图生成器
def getk(s):
    random.seed(s)
    return random.choice([0]*50 + [1]*38 + [2]*5 + [3]*5 + [4, 5])
def getm(n, w):
    lis = []
    for i in range(n):
        lis2 = []
        for j in range(w):
            lis2.append(getk(gameseed + 10*i + j))
        lis.append(lis2)
    return lis

# 初始化
pygame.init()
screen = pygame.display.set_mode((500, 600))
pygame.display.set_caption("矿工游戏")
font = lambda s, w, c: pygame.font.SysFont("Consolas", s).render(w, True, c)
kmap = [[0, 0, 0, 0, 0]] * 3 + [[0, 0, 1, 0, 0]] * 2 + getm(310, 5)
slide = 0
man = pygame.image.load("man.png")
pygame.display.set_icon(man)
mancur = 2
manslide = 2
gameover = False
score = 0
bscore = [0, 0, 3, 5, 10, 20]
time_s = datetime.now()

# 后台处理
# 地图上移
def updslide():
    global slide, score, gameover
    while not gameover:
        time.sleep(0.5)
        slide += 1
        if score >= 300:
            gameover = True
# 矿工下落
delay = 0.3
def down():
    global manslide, score, delay
    while not gameover:
        time.sleep(delay)
        if kmap[manslide+1][mancur] == 0:
            manslide += 1
            score += 1
            delay = 1 / (1/delay + 1/0.3) # 重力加速度
        else:
            delay = 0.3
# 计时
dt = datetime.now()
def go_t():
    global dt
    while not gameover:
        pass
    dt = datetime.now()
#人机
def auto():
    global mancur, kmap, manslide, score
    while not gameover:
        if manslide == slide + 4:
            continue
        kckpt = kmap[:]
        sl = kckpt[slide+4][:]
        if sl == [0, 0, 0, 0, 0]:
            continue
        tsl = []
        ts = slide + 4
        for j, i in enumerate(sl):
            if i > 0:
                tsl.append(j)
        tsl = min(tsl, key=lambda i: abs(i-mancur))
        if abs(tsl - mancur) > 1:
            n_ct = True
            for i in range(manslide, slide+4):
                n_ct = n_ct and kckpt[i][tsl]
            if n_ct:
                continue
        if tsl < mancur:
            while tsl != mancur:
                if kmap[manslide+1][mancur]:
                    mancur -= 1
                    if kmap[manslide][mancur]:
                        score += bscore[kmap[manslide][mancur]]
                        kmap[manslide][mancur] = 0
                elif kmap[manslide][mancur-1] == 0:
                    mancur -= 1
        elif tsl > mancur:
            while tsl != mancur:
                if kmap[manslide+1][mancur] != 0:
                    mancur += 1
                    if kmap[manslide][mancur]:
                        score += bscore[kmap[manslide][mancur]]
                        kmap[manslide][mancur] = 0
                elif kmap[manslide][mancur+1]==0:
                    mancur += 1
        while manslide < ts-2:
            if kmap[manslide+1][mancur]:
                score += bscore[kmap[manslide+1][mancur]]
                kmap[manslide+1][mancur] = 0
            else:
                manslide += 1
                score += 1
_thread.start_new_thread(updslide, ())
_thread.start_new_thread(down, ())
_thread.start_new_thread(go_t, ())
if do_ai.get() == 1:
    _thread.start_new_thread(auto, ())

# 游戏循环
while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            # 退出
            pygame.quit()
            sys.exit()
        if event.type == KEYDOWN:
            # 移动
            if not gameover:
                if event.key == K_LEFT and mancur != 0:
                    if kmap[manslide+1][mancur]:
                        mancur -= 1
                        if kmap[manslide][mancur]:
                            score += bscore[kmap[manslide][mancur]]
                            kmap[manslide][mancur] = 0
                    elif kmap[manslide][mancur-1] == 0:
                        mancur -= 1
                if event.key == K_RIGHT and mancur != 4:
                    if kmap[manslide+1][mancur] != 0:
                        mancur += 1
                        if kmap[manslide][mancur]:
                            score += bscore[kmap[manslide][mancur]]
                            kmap[manslide][mancur] = 0
                    elif kmap[manslide][mancur+1] == 0:
                        mancur += 1
                if event.key == K_DOWN:
                    if kmap[manslide+1][mancur]:
                        score += bscore[kmap[manslide+1][mancur]]
                        kmap[manslide+1][mancur] = 0
                    else:
                        manslide += 1
                        score += 1
    # 游戏结束的判断
    if manslide < slide or manslide >= slide+4:
        gameover = True
    # 绘制
    screen.fill("lightgray")
    for i in range(slide, slide+5):
        for j in range(5):
            if kmap[i][j] == 1:
                pygame.draw.rect(screen, (80, 80, 80), pygame.Rect(j*100+5, (i-slide)*100+5, 90, 90))
            if kmap[i][j] == 2:
                pygame.draw.rect(screen, "black", pygame.Rect(j*100+5, (i-slide)*100+5, 90, 90))
            if kmap[i][j] == 3:
                pygame.draw.rect(screen, (186, 110, 64), pygame.Rect(j*100+5, (i-slide)*100+5, 90, 90))
            if kmap[i][j] == 4:
                pygame.draw.rect(screen, "gold", pygame.Rect(j*100+5, (i-slide)*100+5, 90, 90))
            if kmap[i][j] == 5:
                pygame.draw.rect(screen, (64, 128, 255), pygame.Rect(j*100+5, (i-slide)*100+5, 90, 90))
    screen.blit(man, (mancur*100+5, (manslide-slide)*100+5))
    if gameover:
        # 游戏结束界面
        screen.fill("lightgray")
        go = font(48, "GAME OVER", "green")
        tip = font(24, "Restart the program to play again", "blue")
        screen.blit(go, (133, 200))
        screen.blit(tip, (36, 300))
    # 得分、时间、种子
    sc = font(24, "Score: {}".format(score), "black")
    if gameover:
        delta = dt-time_s
    else:
        delta = datetime.now()-time_s
    s = delta.seconds
    minutes, seconds = divmod(s, 60)
    ts = font(24, "Time: {:02}:{:02}".format(int(minutes), int(seconds)), "black")
    gs = font(24, "Seed: {}".format(gameseed), "black")
    screen.blit(sc, (50, 500))
    screen.blit(ts, (50, 550))
    screen.blit(gs, (250, 500))
    pygame.display.flip()
